import java.io.File;
import java.util.*;

import benchmark.Benchmarker;

import tools.*;


public class Main {

	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		String fileName = "";
		for (String s : args) {
			fileName += s + "_";
		}
		fileName += ".data";
		fileName = "buffer.data";
		String instruction = args[0];
//		int repeatTime = Integer.parseInt(args[2]);
//		List<String> argsList = Arrays.asList(Arrays.copyOfRange(args, 1, args.length));
//		List<List<String>> splitedArgs = new ArrayList<List<String>>();
//		for (String arg : argsList) {
//			splitedArgs.add(Arrays.asList(arg.split(",")));
//		}
//		
//		System.out.println(splitedArgs.toString());

		try {
			Tree<String> tree = new Tree<String>(instruction);
			
			for (int i = 1; i < args.length; i++) {
				List<String> arg = new ArrayList<String>();
				String[] scale = args[i].split(",");
				if(scale.length == 3) {
					int start = Integer.parseInt(scale[0]);
					int end = Integer.parseInt(scale[1]);
					String operator = scale[2].substring(0, 1);
					int step = Integer.parseInt(scale[2].substring(1));
					if (operator.equals("+")) {
						for (int j = start; j <= end; j += step) {
							arg.add(Integer.toString(j));
						}
					} else if (operator.equals("*")) {
						for (int j = start; j <= end; j *= step) {
							arg.add(Integer.toString(j));
						}
					} else {
						throw new Exception("Invalide arg.");
					}
				} else if(scale.length == 1) {
					arg.add(scale[0]);
				} else {
						throw new Exception("Invalide arg.");
				}
				for (String s : arg) {
					tree.add2Level(s, i - 1);
				}
			}
			List<LinkedList<String>> paths = (List<LinkedList<String>>) tree.getAllPath();


			// remove the 'instruction', 'file name' and 'repeat time'
//			for (LinkedList<String> path : paths) {
//				path.removeFirst();
//				path.removeFirst();
////				path.removeFirst();
//			}
			
			System.out.println(paths.size() + " loops.");
//			System.out.println(paths);

			
			int totalWorkAmount = paths.size();
			int percentageDone = 0;
			int counter = 0;
			
			String log = "";
			
			long startTime = System.currentTimeMillis();
			for (LinkedList<String> arg : paths) {
				// show progress
				int progress = counter * 100 / totalWorkAmount;
				if (progress > percentageDone) {
					percentageDone = progress;
					System.out.format("%d percent done.(%dms)\n", percentageDone, System.currentTimeMillis() - startTime);
				}
				// do the work
//				AbstractTask task = TaskFactory.getTask(instruction, arg);
//				long result = task.compute();
//				String record = "";
//				for (String a : arg) {
//					record += a + "\t";
//				}
				
//				String record = TaskFactory.runTask(instruction, arg);
				String record = Benchmarker.run(arg);
				
				// output log
//				record += Long.toString(result) + "\n";
				log += record;
//				System.gc();
				counter++;
			}
			System.out.format("%d percent done.(%dms)\n", 100, System.currentTimeMillis() - startTime);
			
			// log to file
			Output.toFile(log, new File(fileName));
		
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			
		

		
//		tree.showTree();
		

		
		/*
		
		try {
			String accessMode = args[0];
			
			switch (accessMode) {
			case "sread":
				break;
			}
			
			
			List<String> subArgs = new ArrayList<String>();
			for (String a : args) {
				String[] splited = a.split(",");
				if (splited.length == 3) {
					long start = Long.parseLong(splited[0]);
					long end = Long.parseLong(splited[1]);
					long step = Long.parseLong(splited[2]);
					for (long i = start; i <= end; i += step) {
						
					}
				}
			}

			
			List<Integer> argArraySize = new ArrayList<Integer>();
			for(String s : args[1].split(",")) {
				argArraySize.add(Integer.parseInt(s));
			}
			
			List<Integer> argElementSize = new ArrayList<Integer>();
			for(String s : args[2].split(",")) {
				argElementSize.add(Integer.parseInt(s));
			}
			
			List<Integer> argTNum = new ArrayList<Integer>();
			for(String s : args[3].split(",")) {
				argTNum.add(Integer.parseInt(s));
			}
			
			
			String output = args[4];
			
			int runTimes = 1000;
			if(args.length == 6) {
				runTimes = Integer.parseInt(args[5]);
			}
			
			System.out.println("output: " + output);
			System.out.println("arraySize: " + argArraySize);
			System.out.println("elementSize: " + argElementSize);
			System.out.println("tNum: " + argTNum);
			System.out.println("accessMode: " + accessMode);
			System.out.println("runTimes: " + runTimes);
			
			int arraySizeStart = argArraySize.get(0);
			int arraySizeEnd = argArraySize.get(0);
			int arraySizeStep = 1;
			
			if(argArraySize.size() == 3) {
				arraySizeEnd = argArraySize.get(1);
				arraySizeStep = argArraySize.get(2);
			}

			
			int elementSizeStart = argElementSize.get(0);
			int elementSizeEnd = argElementSize.get(0);
			int elementSizeStep = 1;
			
			if(argElementSize.size() == 3) {
				elementSizeEnd = argElementSize.get(1);
				elementSizeStep = argElementSize.get(2);
				if (elementSizeStart < 2 || elementSizeEnd > 13) {
					throw new Exception("Element size out of range, should between 2-13");
				}
			}
			
			
			int tNumStart = argTNum.get(0);
			int tNumEnd = argTNum.get(0);
			int tNumStep = 1;
			
			if(argTNum.size() == 3) {
				tNumEnd = argTNum.get(1);
				tNumStep = argTNum.get(2);
			}
			
			int totalLoops = ((arraySizeEnd - arraySizeStart) / arraySizeStep + 1) * 
					((elementSizeEnd - elementSizeStart) / elementSizeStep + 1) *
					((tNumEnd - tNumStart) / tNumStep + 1);
			
			System.out.format("totally %d tasks.\n", totalLoops);
			
			
			int percentageDone = 0;
			
			int counter = 0;
			
			String results = "";
			long startTime = System.currentTimeMillis();
			
			for (int arraySize = arraySizeStart; arraySize <= arraySizeEnd; arraySize += arraySizeStep) {
				for (int elementSize = elementSizeStart; elementSize <= elementSizeEnd; elementSize += elementSizeStep) {
					for (int tNum = tNumStart; tNum <= tNumEnd; tNum += tNumStep) {
						// display the progress
						int currentDone = counter * 100 / totalLoops;
						if (currentDone > percentageDone) {
							percentageDone = currentDone;
							System.out.format("%d percent done.(%dms)\n", percentageDone, System.currentTimeMillis() - startTime);
						}
						counter++;
						
						// do the work
						results += TaskRunner.runTask(arraySize, elementSize, tNum, accessMode, runTimes);
					}
				}
			} // triple-for ends

			System.out.format("%d percent done.(%dms)\n", 100, System.currentTimeMillis() - startTime);
			
			Output.toFile(results, new File(output));
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		*/


	}
	
	
	
	
	

	
	public static void output() {
		Object[] data = new Object[4];
		data[0] = 100;
		data[1] = 100000000;
		data[2] = 0.5;
		data[3] = "hello!";
		
		Output.toFile(data, new File("test.txt"));
	}
	

}
